﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows.Forms;
using DevExpress.XtraEditors;
using DevExpress.XtraBars;
using XCI.Windows.Core;
using XCI.Sys.Model;
using XCI.Helper;
using XCI.Extensions;
using XCI.Windows.Helper;
using XCI.Core;
using XCI.Sys.Service;
using System.IO;
using System.Drawing.Imaging;
using XCI.Windows.Forms;
using XCI.Sys.Core;

namespace XCI.Sys.Controls
{
    public partial class ImageUploadControl : UserControl
    {
        public ImageUploadControl()
        {
            InitializeComponent();
            openFile.Filter = "PNG文件 (*.png)|*.png|GIF文件 (*.gif)|*.gif|JPEG文件 (*.jpg;*.jpeg)|*.jpg;*.jpeg|所有图像文件 |*.bmp;*.gif;*.jpg;*.jpeg;*.png;|所有文件 |*.*";
            saveFile.Filter = "PNG文件 (*.png)|*.png|GIF文件 (*.gif)|*.gif|JPEG 文件 (*.jpg)|*.jpg|位图文件 (*.bmp)|*.bmp";
        }

        private string _editValue;
        private string _selectPath;
        private Image initImage;

        /// <summary>
        ///图片控件
        /// </summary>
        [Browsable(true), Category("XCI控件"), Description("图片控件")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public PictureEdit PictureEdit => pictureEdit1;

        /// <summary>
        /// 初始图片
        /// </summary>
        [Browsable(true), Category("XCI控件"), Description("默认图片"), DefaultValue(null)]
        public virtual Image InitImage
        {
            get { return initImage; }
            set
            {
                initImage = value;
                pictureEdit1.Image = value;
                Status = ImageUploadStatus.Init;
            }
        }

        /// <summary>
        /// Bar控件
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public BarManager BarControl => barManager1;

        /// <summary>
        /// 工具条控件
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Bar ToolBarControl => bar1;

        /// <summary>
        /// 等待面板
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public XCIOverlayForm OverlayForm { get; } = new XCIOverlayForm();

        /// <summary>
        /// 文件上传状态
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ImageUploadStatus Status { get; private set; } = ImageUploadStatus.Init;

        /// <summary>
        /// 是否显示工具栏
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("是否显示工具栏")]
        public bool ToolbarVisable { get; set; } = true;

        /// <summary>
        /// 选择按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("选择按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem SelectButton
        {
            get => btnSelect;
        }

        /// <summary>
        /// 移除按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("移除按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem RemoveButton
        {
            get => btnRemove;
        }

        /// <summary>
        /// 上传按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("上传按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem UploadButton
        {
            get => btnUpload;
        }

        /// <summary>
        /// 导出按钮
        /// </summary>
        [Browsable(true), Category("XCI按钮"), Description("导出按钮")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public BarButtonItem ExportButton
        {
            get => btnExport;
        }

        /// <summary>
        /// 上传子文件夹（默认自动获取）
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("上传子文件夹（默认自动生成）")]
        public string UploadFolder { get; set; }

        /// <summary>
        /// 上传文件名（默认自动获取）
        /// </summary>
        [Browsable(true), Category("XCI上传"), Description("上传文件名（默认自动生成）")]
        public string UploadFileName { get; set; }

        /// <summary>
        /// 本地文件优先加载（如果存在本地文件则不去加载服务读取）
        /// </summary>
        [Browsable(true), Category("XCI上传"), DefaultValue(true), Description("本地文件优先加载（如果存在本地文件则不去加载服务读取）")]
        public bool LocalFirst { get; set; } = true;

        /// <summary>
        /// 获取或设置指定当前选定值。
        /// </summary>
        [Category("Data"), Description("获取或设置指定当前选定值。")]
        [Browsable(false), Bindable(true), DefaultValue(null)]
        public string EditValue
        {
            get { return _editValue; }
            set
            {
                _editValue = value;
                if (value.IsEmpty())
                {
                    pictureEdit1.Image = initImage;
                }
                else
                {
                    LoadImage(_editValue);
                }
            }
        }

        /// <summary>
        /// 是否有照片
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool HasImage
        {
            get
            {
                return pictureEdit1.Image != null && (_editValue.IsNotEmpty() || _selectPath.IsNotEmpty());
            }
        }


        /// <summary>
        /// 是否需要上传
        /// </summary>
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public bool RequiredUpload
        {
            get
            {
                return pictureEdit1.Image != null && _selectPath != null && Status == ImageUploadStatus.Waiting;
            }
        }

        [Category("XCI事件"), Description("图片加载前事件")]
        public event EventHandler<ImageBeforeEventArgs> BeforeLoad;

        [Category("XCI事件"), Description("图片加载完成事件")]
        public event EventHandler<ImageEventArgs> LoadCompleted;

        [Category("XCI事件"), Description("图片选择前事件")]
        public event EventHandler<ImageBeforeEventArgs> BeforeSelect;

        [Category("XCI事件"), Description("图片选择完成事件")]
        public event EventHandler<ImageEventArgs> SelectCompleted;

        [Category("XCI事件"), Description("图片移除前事件")]
        public event EventHandler<ImageBeforeEventArgs> BeforeRemove;

        [Category("XCI事件"), Description("图片移除完成事件")]
        public event EventHandler<ImageEventArgs> RemoveCompleted;

        [Category("XCI事件"), Description("图片保存前事件")]
        public event EventHandler<ImageBeforeEventArgs> BeforeSave;

        [Category("XCI事件"), Description("图片保存完成事件")]
        public event EventHandler<ImageEventArgs> SaveCompleted;

        [Category("XCI事件"), Description("图片上传前事件")]
        public event EventHandler<ImageBeforeEventArgs> BeforeUpload;

        [Category("XCI事件"), Description("图片上传完成事件")]
        public event EventHandler<ImageUploadEventArgs> UploadCompleted;

        /// <summary>
        /// 生成右键菜单
        /// </summary>
        private void BuildPopupMenuCore()
        {
            foreach (BarItem item in barManager1.Items)
            {
                //if (!(item is BarButtonItem)) continue;
                popupMenu1.ItemLinks.Add(item);
            }
        }

        /// <summary>
        /// 设置按钮状态
        /// </summary>
        private void SetButtonStatus()
        {
            var hasImage = pictureEdit1.Image != null;
            btnRemove.Enabled = hasImage && Status != ImageUploadStatus.Init;
            btnUpload.Enabled = hasImage && Status == ImageUploadStatus.Waiting;
            btnExport.Enabled = hasImage && Status != ImageUploadStatus.Init;
            btnPreview.Enabled = hasImage && Status != ImageUploadStatus.Init;
        }

        /// <summary>
        /// 设置状态
        /// </summary>
        public void SetStatus(ImageUploadStatus status)
        {
            Status = status;
        }

        /// <summary>
        /// 加载图片
        /// </summary>
        /// <param name="path">图片路径（服务器路径）</param>
        public void LoadImage(string path)
        {
            var args = new ImageBeforeEventArgs();
            BeforeLoad?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }
            
            var localPath = WinHelper.BuildLocalPathByServerPath(path);
            var fileInfo = new FileInfo(localPath);
            if (LocalFirst && fileInfo.Exists)
            {
                pictureEdit1.Image = ImageHelper.LoadImage(localPath);
                Status = ImageUploadStatus.Finished;
                SetButtonStatus();
                LoadCompleted?.Invoke(this, new ImageEventArgs());
                return;
            }

            if (string.IsNullOrEmpty(localPath)) return;
            var md5 = string.Empty;
            if (fileInfo.Exists)
            {
                md5 = StringHelper.Md5File(localPath);
            }

            OverlayForm.Show(this);
            Task.Run(() =>
            {
                FileUploadService.Instance.Download(path, localPath, md5, p =>
                {
                    OverlayForm.SetText($"正在下载... {p.ProgressPercentage.ToString()}%");
                });
            }).ContinueWith(p =>
            {
                if (File.Exists(localPath))
                {
                    pictureEdit1.Image = ImageHelper.LoadImage(localPath);
                    Status = ImageUploadStatus.Finished;
                }
                SetButtonStatus();
                LoadCompleted?.Invoke(this, new ImageEventArgs());
                OverlayForm.Close();
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 加载图片
        /// </summary>
        /// <param name="recordId">主键</param>
        public void LoadImageByRecordId(string recordId)
        {
            var model = FileService.Instance.SelectByRecordId(recordId);
            if (model == null)
            {
                return;
            }
            LoadImage(model.Url);
        }

        /// <summary>
        /// 选择图片
        /// </summary>
        public void SelectImage()
        {
            var args = new ImageBeforeEventArgs();
            BeforeSelect?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            this.openFile.FilterIndex = this.openFile.Filter.Split('|').Length / 2 - 1;
            if (this.openFile.ShowDialog() != DialogResult.OK) return;
            if (this.openFile.FileName.IsEmpty()) return;
            if (!ImageHelper.IsImage(this.openFile.FileName))
            {
                MessageBoxHelper.ShowWarn("请选择有效的图片文件");
                return;
            }

            OverlayForm.Show(this);
            OverlayForm.SetText("正在加载...");
            if (pictureEdit1.Image != null) pictureEdit1.Image.Dispose();
            pictureEdit1.Image = null;

            try
            {
                _selectPath = openFile.FileName;
                btnSelect.Enabled = false;
                pictureEdit1.Image = ImageHelper.LoadImage(_selectPath);
                Status = ImageUploadStatus.Waiting;
                SetButtonStatus();
                SelectCompleted?.Invoke(this, new ImageEventArgs());
            }
            finally
            {
                btnSelect.Enabled = true;
                OverlayForm.Close();
            }
        }

        /// <summary>
        /// 设置待上传的图片
        /// </summary>
        /// <param name="imgPath">图片路径</param>
        public void SetWaitingImage(string imgPath)
        {
            var args = new ImageBeforeEventArgs();
            BeforeSelect?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (imgPath.IsEmpty() || !ImageHelper.IsImage(imgPath))
            {
                //MessageBoxHelper.ShowWarn("请指定有效的图片文件");
                return;
            }

            OverlayForm.Show(this);
            OverlayForm.SetText("正在加载...");
            if (pictureEdit1.Image != null) pictureEdit1.Image.Dispose();
            pictureEdit1.Image = null;

            try
            {
                _selectPath = imgPath;
                btnSelect.Enabled = false;
                pictureEdit1.Image = ImageHelper.LoadImage(_selectPath);
                Status = ImageUploadStatus.Waiting;
                SetButtonStatus();
                SelectCompleted?.Invoke(this, new ImageEventArgs());
            }
            finally
            {
                btnSelect.Enabled = true;
                OverlayForm.Close();
            }
        }

        /// <summary>
        /// 移除图片
        /// </summary>
        public void RemoveImage()
        {
            var args = new ImageBeforeEventArgs();
            BeforeRemove?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (MessageBoxHelper.ShowMessageYesNo("确定要移除当前图片吗？") != DialogResult.Yes) return;

            try
            {
                if (_editValue.IsNotEmpty() && Status == ImageUploadStatus.Finished)
                {
                    FileUploadService.Instance.Delete(_editValue);
                }
                if (pictureEdit1.Image != null) pictureEdit1.Image.Dispose();
            }
            finally
            {
                Status = ImageUploadStatus.Init;
                pictureEdit1.Image = null;
                SetButtonStatus();
                RemoveCompleted?.Invoke(this, new ImageEventArgs());
            }
        }

        /// <summary>
        /// 上传图片
        /// </summary>
        public void UploadImage(Action<ImageUploadEventArgs> completedCallback = null)
        {
            var args = new ImageBeforeEventArgs();
            BeforeUpload?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (pictureEdit1.Image == null || _selectPath.IsEmpty() || Status == ImageUploadStatus.Finished)
            {
                completedCallback?.Invoke(new ImageUploadEventArgs { FileModelInfo = new BoolMessage<FileModel>(true) });
                return;
            }

            OverlayForm.Show(this);
            BoolMessage<FileModel> uploadResult = null;
            Task.Run(() =>
            {
                var fileInfo = new FileInfo(_selectPath);
                uploadResult = FileUploadService.Instance.UploadFileAsMessage(UploadFolder, UploadFileName, fileInfo.Name, fileInfo.FullName, p =>
                {
                    Status = ImageUploadStatus.Uploading;
                    OverlayForm.SetText($"正在上传... {p.ProgressPercentage.ToString()}%");
                });
            }).ContinueWith(p =>
            {
                if (uploadResult.Success)
                {
                    _editValue = uploadResult.Data.Url;
                    Status = ImageUploadStatus.Finished;
                }
                SetButtonStatus();
                OverlayForm.Close();
                var iargs = new ImageUploadEventArgs { FileModelInfo = uploadResult };
                UploadCompleted?.Invoke(this, iargs);
                completedCallback?.Invoke(iargs);
            }, TaskScheduler.FromCurrentSynchronizationContext());
        }

        /// <summary>
        /// 保存图片
        /// </summary>
        public void ExportImage()
        {
            var args = new ImageBeforeEventArgs();
            BeforeSave?.Invoke(this, args);
            if (args.Cancel)
            {
                return;
            }

            if (pictureEdit1.Image == null)
            {
                MessageBoxHelper.ShowWarn("当前没有图片");
                return;
            }
            if (_editValue.IsNotEmpty())
            {
                saveFile.FileName = Path.GetFileName(_editValue);
            }
            else if (_selectPath.IsNotEmpty())
            {
                saveFile.FileName = Path.GetFileName(_selectPath);
            }
            if (this.saveFile.ShowDialog() == DialogResult.OK)
            {
                FileInfo fileInfo = new FileInfo(this.saveFile.FileName);
                FileStream fileStream = null;
                try
                {
                    if (fileInfo.Exists)
                        fileInfo.Delete();
                    fileStream = new FileStream(this.saveFile.FileName, FileMode.Create);
                    ImageFormat format;
                    switch (this.saveFile.FilterIndex)
                    {
                        case 1:
                            format = ImageFormat.Bmp;
                            break;
                        case 2:
                            format = ImageFormat.Gif;
                            break;
                        case 4:
                            format = ImageFormat.Png;
                            break;
                        default:
                            format = ImageFormat.Jpeg;
                            break;
                    }
                    pictureEdit1.Image.Save(fileStream, format);
                    SaveCompleted?.Invoke(this, new ImageEventArgs());
                    MessageBoxHelper.ShowWarn("保存成功");
                }
                catch (Exception ex)
                {
                    XtraMessageBox.Show(ex.Message, ex.Source, MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
                finally
                {
                    fileStream?.Close();
                }
            }
        }

        /// <summary>
        /// 预览图片
        /// </summary>
        public void PreviewImage()
        {
            if (pictureEdit1.Image == null)
            {
                MessageBoxHelper.ShowWarn("当前没有图片");
                return;
            }
            FrmImagePreview imagePreview = null;
            if (_editValue.IsNotEmpty())
            {
                var localPath = WinHelper.BuildLocalPathByServerPath(_editValue);
                imagePreview = new FrmImagePreview(localPath);
            }
            else if (_selectPath.IsNotEmpty())
            {
                imagePreview = new FrmImagePreview(_selectPath);
            }
            else if (pictureEdit1.Image != null)
            {
                imagePreview = new FrmImagePreview(pictureEdit1.Image);
            }

            if (imagePreview != null)
            {
                imagePreview.Size = WinHelper.GetImagePreviewSize();
                imagePreview.Show();
            }
        }

        private void ImageUploadControl_Load(object sender, EventArgs e)
        {
            bar1.Visible = ToolbarVisable;
            BuildPopupMenuCore();
            SetButtonStatus();
        }

        private void PictureEdit1_PopupMenuShowing(object sender, DevExpress.XtraEditors.Events.PopupMenuShowingEventArgs e)
        {
            e.Cancel = true;
            popupMenu1.ShowPopup(Control.MousePosition);
        }

        private void PictureEdit1_DoubleClick(object sender, EventArgs e)
        {
            PreviewImage();
        }

        private void BtnSelect_ItemClick(object sender, ItemClickEventArgs e)
        {
            SelectImage();
        }

        private void BtnRemove_ItemClick(object sender, ItemClickEventArgs e)
        {
            RemoveImage();
        }

        private void BtnUpload_ItemClick(object sender, ItemClickEventArgs e)
        {
            UploadImage();
        }

        private void BtnSave_ItemClick(object sender, ItemClickEventArgs e)
        {
            ExportImage();
        }

        private void BtnPreview_ItemClick(object sender, ItemClickEventArgs e)
        {
            PreviewImage();
        }

        private void PictureEdit1_DragEnter(object sender, DragEventArgs e)
        {
            e.Effect = DragDropEffects.Copy;
        }

        private void PictureEdit1_DragDrop(object sender, DragEventArgs e)
        {
            var files = (string[])e.Data.GetData(DataFormats.FileDrop);
            if (files.Length <= 0) return;
            var filePath = files[0];
            try
            {
                SetWaitingImage(filePath);
            }
            catch
            {
                MessageBoxHelper.ShowError("无效的图片文件");
            }
        }
    }
}
